package com.xsystem.criteria;

import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;

public class XsystemProjection {
	
	public enum ProjectionType {
		PROPERTY, GROUP_PROPERTY, AVG, COUNT, COUNT_DISTINCT, DISTINCT, MAX, MIN, ROW_COUNT, SUM, SQL_PROJECTION, SQL_GROUP_PROJECTION
	}

	private ProjectionType projectionType;
	
	private String propertyName;
	
	private String alias;
	
	private XsystemProjection(ProjectionType projectionType, String propertyName) {
		this.projectionType = projectionType;
		this.propertyName = propertyName;
	}
	
	public static XsystemProjection property(String propertyName) {
		return createProjection(ProjectionType.PROPERTY, propertyName);
	}
	
	public static XsystemProjection groupProperty(String propertyName) {
		return createProjection(ProjectionType.GROUP_PROPERTY, propertyName);
	}
	
	public static XsystemProjection avg(String propertyName) {
		return createProjection(ProjectionType.AVG, propertyName);
	}
	
	public static XsystemProjection count(String propertyName) {
		return createProjection(ProjectionType.COUNT, propertyName);
	}
	
	public static XsystemProjection countDistinct(String propertyName) {
		return createProjection(ProjectionType.COUNT_DISTINCT, propertyName);
	}
	
	public static XsystemProjection distinct() {
		return createProjection(ProjectionType.DISTINCT, null);
	}
	
	public static XsystemProjection min(String propertyName) {
		return createProjection(ProjectionType.MIN, propertyName);
	}
	
	public static XsystemProjection max(String propertyName) {
		return createProjection(ProjectionType.MAX, propertyName);
	}
	
	public static XsystemProjection sum(String propertyName) {
		return createProjection(ProjectionType.SUM, propertyName);
	}
	
	public static XsystemProjection rowCount() {
		return createProjection(ProjectionType.ROW_COUNT, null);
	}
	
	public static XsystemProjection alias(XsystemProjection projection, String alias) {
		return projection.as(alias);
	}
	
	public XsystemProjection as(String alias) {
		this.alias = alias;
		return this;
	}
	
	private static XsystemProjection createProjection(ProjectionType projectionType, String propertyName) {
		return new XsystemProjection(projectionType, propertyName);
	}
	
	public Projection toHibernateProjection() {
		Projection result = null;
		if (projectionType == ProjectionType.PROPERTY) {
			result = Projections.property(propertyName);
		} else if (projectionType == ProjectionType.GROUP_PROPERTY) {
			result = Projections.groupProperty(propertyName);
		} else if (projectionType == ProjectionType.AVG) {
			result = Projections.avg(propertyName);
		} else if (projectionType == ProjectionType.COUNT) {
			result = Projections.count(propertyName);
		} else if (projectionType == ProjectionType.COUNT_DISTINCT) {
			result = Projections.countDistinct(propertyName);
		} else if (projectionType == ProjectionType.MAX) {
			result = Projections.max(propertyName);
		} else if (projectionType == ProjectionType.MIN) {
			result = Projections.min(propertyName);
		} else if (projectionType == ProjectionType.SUM) {
			result = Projections.sum(propertyName);
		} else if (projectionType == ProjectionType.ROW_COUNT) {
			result = Projections.rowCount();
		} else if (projectionType == ProjectionType.SQL_PROJECTION) {
			throw new UnsupportedOperationException("Not supported yet!");
		} else if (projectionType == ProjectionType.SQL_GROUP_PROJECTION) {
			throw new UnsupportedOperationException("Not supported yet!");
		}
		return result;
	}
	
	public ProjectionType getProjectionType() {
		return projectionType;
	}
	
	public String getPropertyName() {
		return propertyName;
	}
	
	public String getAlias() {
		return alias;
	}
}
